#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
链接提取模块
负责从页面中提取蓝奏云链接和密码
"""

import re
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException

class LinkExtractor:
    """链接提取类，负责从页面中提取蓝奏云链接和密码"""
    
    def __init__(self, driver):
        """初始化链接提取器
        
        Args:
            driver: WebDriver对象
        """
        self.driver = driver
        self.wait = WebDriverWait(self.driver, 10)
    
    def extract_lanzou_links(self):
        """从当前页面提取蓝奏云下载链接和对应的密码
        
        Returns:
            tuple: (下载链接, 密码)，链接未找到时返回(None, None)
        """
        print("\n开始提取蓝奏云下载链接和密码...")
        
        # 获取页面源码
        page_source = self.driver.page_source
        
        # 使用多种模式匹配蓝奏云链接和密码
        patterns = [
            # 模式1: 标准格式 - 链接后跟密码
            r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            # 模式2: 密码格式
            r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:密|密码|pwd|password)\s*[:：]?\s*(\w+)',
            # 模式3: 网盘格式
            r'(?:链接|网盘)[^\w<>]*[:：]?\s*(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
        ]
        
        # 保存找到的所有链接和密码
        found_links_passwords = []
        
        # 使用正则表达式查找匹配项
        for pattern in patterns:
            matches = re.findall(pattern, page_source)
            if matches:
                for match in matches:
                    link, password = match
                    found_links_passwords.append((link, password))
                    print(f"找到链接: {link} - 密码: {password}")
        
        # 如果通过正则表达式找到了匹配项，选择最后一个
        if found_links_passwords:
            last_link, last_password = found_links_passwords[-1]
            print(f"\n选择最后一个链接: {last_link} - 密码: {last_password}")
            return last_link, last_password
        
        # 如果没有通过正则表达式找到匹配项，尝试查找所有包含lanzou的链接
        print("\n通过正则表达式未找到匹配，尝试提取所有蓝奏云链接...")
        
        try:
            # 查找所有链接
            links = self.driver.find_elements(By.TAG_NAME, "a")
            lanzou_links = []
            
            for link in links:
                href = link.get_attribute("href")
                if href and ("lanzou.com" in href or "lanzn.com" in href):
                    lanzou_links.append(href)
                    print(f"找到蓝奏云链接: {href}")
            
            if lanzou_links:
                last_link = lanzou_links[-1]
                print(f"\n选择最后一个链接: {last_link}")
                
                # 尝试在链接附近找到密码
                try:
                    # 获取链接元素的父元素，查找其中的文本
                    for link_element in links:
                        href = link_element.get_attribute("href")
                        if href == last_link:
                            parent = link_element.find_element(By.XPATH, "./..")
                            parent_text = parent.text
                            
                            # 尝试从父元素文本中提取密码
                            pwd_match = re.search(r'(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)', parent_text)
                            if pwd_match:
                                password = pwd_match.group(1)
                                print(f"从链接附近提取到密码: {password}")
                                return last_link, password
                except Exception as e:
                    print(f"尝试提取密码时出错: {str(e)}")
                
                # 如果没有找到密码，返回空密码
                return last_link, ""
            else:
                print("未找到任何蓝奏云链接")
                return None, None
        except Exception as e:
            print(f"提取链接时出错: {str(e)}")
            return None, None
    
    def post_comment(self, comment_text="感谢分享"):
        """在当前页面发表评论
        
        Args:
            comment_text: 评论内容，默认为"感谢分享"
            
        Returns:
            bool: 是否成功发表评论
        """
        print("\n正在尝试发表评论...")
        
        try:
            # 尝试找到评论输入框
            comment_input = self._find_comment_field()
            
            if comment_input:
                # 输入评论内容
                comment_input.clear()
                comment_input.send_keys(comment_text)
                print(f"已输入评论: {comment_text}")
                
                # 查找提交按钮
                submit_button = self._find_comment_submit_button()
                
                if submit_button:
                    # 点击提交按钮
                    submit_button.click()
                    print("已提交评论")
                    
                    # 等待页面刷新
                    print("等待页面刷新...")
                    time.sleep(3)
                    return True
                else:
                    print("未找到评论提交按钮")
            else:
                print("未找到评论输入框")
            
            return False
            
        except Exception as e:
            print(f"尝试评论过程中出错: {str(e)}")
            return False
    
    def _find_comment_field(self):
        """查找评论输入框
        
        Returns:
            WebElement: 评论输入框元素，未找到时返回None
        """
        # 查找可能的评论输入框
        selectors = [
            (By.ID, "message"),
            (By.NAME, "message"),
            (By.ID, "comment"),
            (By.NAME, "comment"),
            (By.CSS_SELECTOR, "textarea.comment"),
            (By.CSS_SELECTOR, "textarea.message"),
            (By.CSS_SELECTOR, "textarea[placeholder*='评论']"),
            (By.XPATH, "//textarea[contains(@placeholder, '评论')]"),
            (By.XPATH, "//div[contains(@class, 'comment')]//textarea"),
            (By.XPATH, "//div[contains(@class, 'reply')]//textarea"),
        ]
        
        for selector_type, selector_value in selectors:
            try:
                elements = self.driver.find_elements(selector_type, selector_value)
                for element in elements:
                    if element.is_displayed() and element.is_enabled():
                        print(f"找到评论输入框: {selector_type} - {selector_value}")
                        return element
            except:
                continue
        
        return None
    
    def _find_comment_submit_button(self):
        """查找评论提交按钮
        
        Returns:
            WebElement: 提交按钮元素，未找到时返回None
        """
        # 查找提交按钮
        selectors = [
            (By.XPATH, "//button[contains(text(), '提交')]"),
            (By.XPATH, "//button[contains(text(), '回复')]"),
            (By.XPATH, "//button[contains(text(), '发表')]"),
            (By.XPATH, "//button[contains(text(), '评论')]"),
            (By.XPATH, "//input[@type='submit']"),
            (By.ID, "submit"),
            (By.CSS_SELECTOR, "button.submit"),
            (By.CSS_SELECTOR, "button[type='submit']"),
        ]
        
        for selector_type, selector_value in selectors:
            try:
                elements = self.driver.find_elements(selector_type, selector_value)
                for element in elements:
                    if element.is_displayed() and element.is_enabled():
                        print(f"找到提交按钮: {selector_type} - {selector_value}")
                        return element
            except:
                continue
        
        return None
    
    def check_all_links(self, auto_select=False):
        """检查页面上的所有链接，并让用户选择
        
        Args:
            auto_select: 是否自动选择第一个链接，不询问用户
        
        Returns:
            str: 用户选择的链接URL，未选择时返回None
        """
        try:
            all_links = self.driver.find_elements(By.TAG_NAME, "a")
            print(f"\n页面上共有 {len(all_links)} 个链接")
            
            # 显示所有有文本的链接
            link_count = 0
            visible_links = []
            
            for link in all_links:
                link_text = link.text
                href = link.get_attribute("href")
                if link_text and href:
                    link_count += 1
                    visible_links.append((link, link_text, href))
                    if link_count <= 10:  # 最多显示10个链接
                        print(f"{link_count}. {link_text}: {href}")
            
            if link_count > 10:
                print(f"... 还有 {link_count-10} 个链接未显示")
            
            if link_count > 0:
                # 自动选择模式下，直接选择第一个链接
                if auto_select:
                    print(f"自动选择第一个链接: {visible_links[0][1]}")
                    return visible_links[0][2]
                else:
                    # 询问是否要打开特定链接
                    print(f"\n请输入要打开的链接编号 (1-{link_count}): ")
                    try:
                        link_num = int(input())
                        if 1 <= link_num <= link_count:
                            _, _, specific_url = visible_links[link_num-1]
                            return specific_url
                        else:
                            print("无效的链接编号")
                    except ValueError:
                        print("无效的输入")
            
            return None
        
        except Exception as e:
            print(f"查看页面链接时出错: {str(e)}")
            return None
    
    def manual_html_input(self):
        """手动输入HTML内容提取链接和密码
        
        Returns:
            tuple: (下载链接, 密码)，提取失败时返回(None, None)
        """
        print("\n手动HTML输入模式")
        print("-------------------")
        print("请将包含蓝奏云链接和密码的HTML内容粘贴到下面")
        print("(输入完成后按Ctrl+D结束输入)")
        print("-------------------")
        
        # 收集输入的HTML内容
        html_lines = []
        try:
            while True:
                line = input()
                html_lines.append(line)
        except EOFError:
            pass
        
        html_content = "\n".join(html_lines)
        
        if not html_content.strip():
            print("未输入任何内容，退出手动模式")
            return None, None
        
        print(f"\n收到HTML内容，长度: {len(html_content)} 字符")
        
        # 使用与extract_lanzou_links相同的逻辑提取链接和密码
        patterns = [
            r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:密|密码|pwd|password)\s*[:：]?\s*(\w+)',
            r'(?:链接|网盘)[^\w<>]*[:：]?\s*(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
        ]
        
        found_links_passwords = []
        
        for pattern in patterns:
            matches = re.findall(pattern, html_content)
            if matches:
                for match in matches:
                    link, password = match
                    found_links_passwords.append((link, password))
                    print(f"找到链接: {link} - 密码: {password}")
        
        if found_links_passwords:
            last_link, last_password = found_links_passwords[-1]
            print(f"\n选择最后一个链接: {last_link} - 密码: {last_password}")
            return last_link, last_password
        
        # 如果没有通过复杂模式找到，尝试简单匹配蓝奏云链接
        lanzou_link_match = re.search(r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)', html_content)
        if lanzou_link_match:
            link = lanzou_link_match.group(1)
            print(f"找到链接: {link}")
            
            # 尝试在链接附近找密码
            surrounding_text = html_content[max(0, html_content.find(link) - 100):min(len(html_content), html_content.find(link) + 200)]
            pwd_match = re.search(r'(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)', surrounding_text)
            
            if pwd_match:
                password = pwd_match.group(1)
                print(f"从链接附近提取到密码: {password}")
                return link, password
            else:
                print("未找到密码")
                return link, ""
        
        print("未找到任何蓝奏云链接和密码")
        return None, None
    
    def extract_multiple_lanzou_links(self):
        """从当前页面提取所有蓝奏云下载链接和对应的密码
        
        Returns:
            list: 包含(下载链接, 密码)元组的列表，未找到时返回空列表
        """
        print("\n开始提取所有蓝奇云下载链接和密码...")
        
        # 获取页面源码
        page_source = self.driver.page_source
        
        # 使用多种模式匹配蓝奏云链接和密码 (更新为支持更多格式)
        patterns = [
            # 标准模式 - 链接后跟密码
            r'(https?://(?:www\.)?lanz[a-z0-9]*\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            r'(https?://(?:www\.)?lanzn\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            r'(https?://(?:www\.)?lanzoux\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            r'(https?://(?:www\.)?lanzoui\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            r'(https?://(?:[a-z0-9]+\.)?lanzou[a-z0-9]*\.com/[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            
            # 文件夹模式 - 支持i/b格式
            r'(https?://(?:www\.)?lanz[a-z0-9]*\.com/b[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
            r'(https?://(?:www\.)?lanzn\.com/b[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
            r'(https?://(?:www\.)?lanzou[a-z0-9]*\.com/i[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
            
            # 密码模式
            r'(https?://(?:www\.)?lanz[a-z0-9]*\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:密|密码|pwd|password)\s*[:：]?\s*([a-zA-Z0-9]+)',
            r'(https?://(?:www\.)?lanzn\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:密|密码|pwd|password)\s*[:：]?\s*([a-zA-Z0-9]+)',
            
            # 网盘格式
            r'(?:链接|网盘|云盘)[^\w<>]*[:：]?\s*(https?://(?:www\.)?lanz[a-z0-9]*\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
            r'(?:链接|网盘|云盘)[^\w<>]*[:：]?\s*(https?://(?:www\.)?lanzn\.com/(?:s/)?[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
            
            # 短链格式 (蓝奏云使用的短链服务)
            r'(https?://(?:n\.)?lanzouw\.com/[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
            r'(https?://(?:pan\.)?lanzoup\.com/[a-zA-Z0-9_\-]+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]+)',
        ]
        
        # 保存找到的所有链接和密码
        found_links_passwords = []
        found_links = set()  # 用于去重
        
        # 使用正则表达式查找匹配项
        for pattern in patterns:
            matches = re.findall(pattern, page_source)
            if matches:
                for match in matches:
                    link, password = match
                    # 处理链接，确保链接格式正确
                    link = link.strip()
                    # 更新蓝奏云链接域名为其最新域名
                    if 'lanzou' in link and 'lanzouw.com' not in link and 'lanzoup.com' not in link:
                        for old_domain in ['lanzou.com', 'lanzous.com', 'lanzoux.com', 'lanzoui.com', 'lanzn.com']:
                            if old_domain in link:
                                link = link.replace(old_domain, 'lanzouw.com')
                                break
                    
                    # 规范化密码
                    password = password.strip()
                    
                    if link not in found_links:  # 去重
                        found_links.add(link)
                        found_links_passwords.append((link, password))
                        print(f"找到链接: {link} - 密码: {password}")
        
        # 如果通过正则表达式找到了匹配项
        if found_links_passwords:
            print(f"\n通过正则表达式找到了 {len(found_links_passwords)} 个蓝奏云链接")
            return found_links_passwords
        
        # 如果没有通过正则表达式找到匹配项，尝试查找所有包含lanzou的链接
        print("\n通过正则表达式未找到匹配，尝试提取所有蓝奏云链接...")
        
        try:
            # 查找所有链接
            links = self.driver.find_elements(By.TAG_NAME, "a")
            lanzou_links = []
            
            for link in links:
                href = link.get_attribute("href")
                if not href:
                    continue
                
                # 检查是否是蓝奏云链接
                lanzou_domains = ['lanzou', 'lanzn', 'lanzous', 'lanzoux', 'lanzoui', 'lanzouw', 'lanzoup']
                if any(domain in href.lower() for domain in lanzou_domains) and href not in found_links:
                    found_links.add(href)
                    lanzou_links.append(href)
                    print(f"找到蓝奇云链接: {href}")
            
            if lanzou_links:
                # 为找到的每个链接尝试查找对应的密码
                for link_url in lanzou_links:
                    # 尝试在链接附近找到密码
                    password = ""
                    try:
                        # 获取链接元素的父元素，查找其中的文本
                        for link_element in links:
                            href = link_element.get_attribute("href")
                            if href == link_url:
                                # 尝试获取链接及其周围元素的文本
                                surrounding_elements = []
                                
                                # 1. 先获取父元素
                                try:
                                    parent = link_element.find_element(By.XPATH, "./..")
                                    surrounding_elements.append(parent)
                                except:
                                    pass
                                
                                # 2. 尝试获取接下来的兄弟元素
                                try:
                                    next_sibling = link_element.find_element(By.XPATH, "./following-sibling::*[1]")
                                    surrounding_elements.append(next_sibling)
                                except:
                                    pass
                                
                                # 3. 检查父元素的下一个子元素
                                try:
                                    parent = link_element.find_element(By.XPATH, "./..")
                                    next_element = parent.find_element(By.XPATH, "./following-sibling::*[1]")
                                    surrounding_elements.append(next_element)
                                except:
                                    pass
                                
                                # 遍历收集到的元素，尝试找密码
                                for element in surrounding_elements:
                                    element_text = element.text
                                    # 使用正则表达式查找密码
                                    pwd_matches = [
                                        re.search(r'(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]{4,6})', element_text),
                                        re.search(r'(?:密|密码|pwd|password)\s*[:：]?\s*([a-zA-Z0-9]{4,6})', element_text),
                                        re.search(r'([a-zA-Z0-9]{4,6})', element_text)  # 尝试匹配单独的4-6位字母数字组合
                                    ]
                                    
                                    for match in pwd_matches:
                                        if match:
                                            password = match.group(1)
                                            print(f"从元素文本中提取到密码: {password}")
                                            break
                                    
                                    if password:
                                        break
                                
                                # 如果仍未找到密码，尝试在页面源码的相关部分查找
                                if not password:
                                    # 获取链接周围500个字符的文本
                                    surrounding_idx = page_source.find(link_url)
                                    if surrounding_idx > 0:
                                        surrounding_text = page_source[max(0, surrounding_idx - 200):min(len(page_source), surrounding_idx + 300)]
                                        # 尝试多种密码格式
                                        pwd_patterns = [
                                            r'(?:提取|验证|访问)?码\s*[:：]?\s*([a-zA-Z0-9]{4,6})',
                                            r'(?:密|密码|pwd|password)\s*[:：]?\s*([a-zA-Z0-9]{4,6})',
                                            r'([a-zA-Z0-9]{4,6})'  # 尝试匹配单独的4-6位字母数字组合
                                        ]
                                        
                                        for pattern in pwd_patterns:
                                            pwd_match = re.search(pattern, surrounding_text)
                                            if pwd_match:
                                                password = pwd_match.group(1)
                                                print(f"从页面源码中提取到密码: {password}")
                                                break
                                break
                    except Exception as e:
                        print(f"尝试提取密码时出错: {str(e)}")
                    
                    # 添加到结果列表中
                    found_links_passwords.append((link_url, password))
                
                return found_links_passwords
            else:
                print("未找到任何蓝奇云链接")
                return []
        
        except Exception as e:
            print(f"提取链接时出错: {str(e)}")
            return []
    
    def manual_html_extract_links(self):
        """手动输入HTML内容提取所有链接和密码
        
        Returns:
            list: 包含(下载链接, 密码)元组的列表，提取失败时返回空列表
        """
        print("\n手动HTML输入模式")
        print("-------------------")
        print("请将包含蓝奏云链接和密码的HTML内容粘贴到下面")
        print("(输入完成后按Ctrl+D结束输入)")
        print("-------------------")
        
        # 收集输入的HTML内容
        html_lines = []
        try:
            while True:
                line = input()
                html_lines.append(line)
        except EOFError:
            pass
        
        html_content = "\n".join(html_lines)
        
        if not html_content.strip():
            print("未输入任何内容，退出手动模式")
            return []
        
        print(f"\n收到HTML内容，长度: {len(html_content)} 字符")
        
        # 使用与extract_multiple_lanzou_links相同的逻辑提取链接和密码
        patterns = [
            r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
            r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:密|密码|pwd|password)\s*[:：]?\s*(\w+)',
            r'(?:链接|网盘)[^\w<>]*[:：]?\s*(https?://(?:www\.)?lanz[a-z]*\.com/\w+)[^\w<>]*(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)',
        ]
        
        found_links_passwords = []
        found_links = set()  # 用于去重
        
        for pattern in patterns:
            matches = re.findall(pattern, html_content)
            if matches:
                for match in matches:
                    link, password = match
                    if link not in found_links:  # 去重
                        found_links.add(link)
                        found_links_passwords.append((link, password))
                        print(f"找到链接: {link} - 密码: {password}")
        
        if found_links_passwords:
            return found_links_passwords
        
        # 如果没有通过复杂模式找到，尝试简单匹配蓝奏云链接
        lanzou_link_matches = re.findall(r'(https?://(?:www\.)?lanz[a-z]*\.com/\w+)', html_content)
        if lanzou_link_matches:
            for link in lanzou_link_matches:
                if link not in found_links:
                    found_links.add(link)
                    print(f"找到链接: {link}")
                    
                    # 尝试在链接附近找密码
                    surrounding_text = html_content[max(0, html_content.find(link) - 100):min(len(html_content), html_content.find(link) + 200)]
                    pwd_match = re.search(r'(?:提取|验证|访问)?码\s*[:：]?\s*(\w+)', surrounding_text)
                    
                    if pwd_match:
                        password = pwd_match.group(1)
                        print(f"从链接附近提取到密码: {password}")
                        found_links_passwords.append((link, password))
                    else:
                        print("未找到密码")
                        found_links_passwords.append((link, ""))
            
            return found_links_passwords
        
        print("未找到任何蓝奏云链接和密码")
        return [] 